using Kickball.Step1;
using Kickball.Step2;
using Unity.Burst;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;

namespace Kickball.Step3
{
    [UpdateBefore(typeof(TransformSystemGroup))]
    public partial struct BallMovementSystem : ISystem
    {
        [BurstCompile]
        public void OnCreate(ref SystemState state)
        {
            state.RequireForUpdate<Execute.BallMovement>();
            state.RequireForUpdate<Config>();
        }

        [BurstCompile]
        public void OnUpdate(ref SystemState state)
        {
            var config = SystemAPI.GetSingleton<Config>();

            float dt = SystemAPI.Time.DeltaTime;

            float decayFactor = config.BallVelocityDecay * dt; //速度衰减因子
            float ballRadius = 0.5f;
            float minDist = config.ObstacleRadius + ballRadius;
            float minDistSq = minDist * minDist;

            foreach (var (ballTrans, velocity) in SystemAPI.Query<RefRW<LocalTransform>, RefRW<Velocity>>()
                         .WithAll<Ball>().WithDisabled<Carry>())
            {
                if (velocity.ValueRO.Value.Equals(float2.zero)) continue; //静止的球

                float magnitude = math.length(velocity.ValueRO.Value); //速度大小（标量）
                float3 pos = ballTrans.ValueRO.Position +
                             new float3(velocity.ValueRO.Value.x, 0, velocity.ValueRO.Value.y) * dt;

                foreach (var obstacleTrans in SystemAPI.Query<RefRO<LocalTransform>>().WithAll<Obstacle>())
                {
                    if (math.distancesq(obstacleTrans.ValueRO.Position, pos) < minDistSq) //球碰撞到了障碍物
                    {
                        //计算反弹速度和位置
                        pos = DeflectBall(ballTrans.ValueRO.Position, obstacleTrans.ValueRO.Position, velocity,
                            magnitude, dt);
                        break;
                    }
                }

                //球位置
                ballTrans.ValueRW.Position = pos;

                //速度衰减
                float newMagnitude = math.max(magnitude - decayFactor, 0);
                velocity.ValueRW.Value = math.normalizesafe(velocity.ValueRO.Value) * newMagnitude;
            }
        }

        /// <summary>
        /// 偏转球
        /// </summary>
        /// <param name="ballPos">球位置</param>
        /// <param name="obstaclePos">障碍位置</param>
        /// <param name="velocity">速度向量</param>
        /// <param name="magnitude">速度标量</param>
        /// <param name="dt">时间步长</param>
        /// <returns>偏转后球的位置</returns>
        float3 DeflectBall(float3 ballPos, float3 obstaclePos, RefRW<Velocity> velocity, float magnitude, float dt)
        {
            float2 obstacleToBallVector = math.normalize((ballPos - obstaclePos).xz); //障碍指向球的向量（反射的法向量）
            velocity.ValueRW.Value =
                math.reflect(math.normalize(velocity.ValueRO.Value), obstacleToBallVector) * magnitude;
            return ballPos + new float3(velocity.ValueRO.Value.x, 0, velocity.ValueRO.Value.y) * dt;
        }
    }
}